import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:mockito/annotations.dart';
import 'package:flowplan_app/core/sync/data_sync_service.dart';
import 'package:flowplan_app/data/database/app_database.dart';
import 'package:flowplan_app/data/datasources/remote/project_api_service.dart';
import 'package:flowplan_app/data/datasources/remote/auth_api_service.dart';
import 'package:flowplan_app/data/datasources/remote/note_api_service.dart';
import 'package:flowplan_app/data/datasources/remote/todo_api_service.dart';
import 'package:flowplan_app/core/connectivity/connectivity_service.dart';
import 'package:flowplan_app/core/sync/offline_sync_service.dart';
import 'package:flowplan_app/data/models/api_response.dart';
import 'package:flowplan_app/data/models/user_model.dart';
import 'package:flowplan_app/data/models/project_model.dart';
import 'package:flowplan_app/data/models/note_model.dart';
import 'package:flowplan_app/data/models/todo_model.dart';

// 生成Mock类
@GenerateMocks([
  AppDatabase,
  ProjectApiService,
  AuthApiService,
  NoteApiService,
  TodoApiService,
  ConnectivityService,
  OfflineSyncService,
])
import 'data_sync_service_test.mocks.dart';

void main() {
  group('数据同步服务测试', () {
    late MockAppDatabase mockDatabase;
    late MockProjectApiService mockProjectApiService;
    late MockAuthApiService mockAuthApiService;
    late MockNoteApiService mockNoteApiService;
    late MockTodoApiService mockTodoApiService;
    late MockConnectivityService mockConnectivityService;
    late MockOfflineSyncService mockOfflineSyncService;
    late DataSyncService dataSyncService;

    setUp(() {
      mockDatabase = MockAppDatabase();
      mockProjectApiService = MockProjectApiService();
      mockAuthApiService = MockAuthApiService();
      mockNoteApiService = MockNoteApiService();
      mockTodoApiService = MockTodoApiService();
      mockConnectivityService = MockConnectivityService();
      mockOfflineSyncService = MockOfflineSyncService();
      
      dataSyncService = DataSyncService();
    });

    group('初始化', () {
      test('成功初始化服务', () async {
        // 执行初始化
        await dataSyncService.initialize(
          database: mockDatabase,
          projectApiService: mockProjectApiService,
          authApiService: mockAuthApiService,
          noteApiService: mockNoteApiService,
          todoApiService: mockTodoApiService,
          connectivityService: mockConnectivityService,
          offlineSyncService: mockOfflineSyncService,
        );

        // 验证初始化成功
        expect(dataSyncService.currentStatus, SyncStatus.idle);
      });
    });

    group('同步所有数据', () {
      test('成功同步所有数据', () async {
        // 准备测试数据
        final userInfo = UserInfo(
          id: 1,
          username: 'testuser',
          email: 'test@example.com',
          role: 'DEVELOPER',
        );

        final userApiResponse = ApiResponse<UserInfo>(
          success: true,
          message: '成功',
          data: userInfo,
        );

        final projects = [
          ProjectModel(
            id: 1,
            projectName: '项目1',
            description: '项目1描述',
            status: ProjectStatus.inProgress,
            priority: Priority.high,
            creatorId: 1,
            createTime: DateTime.now(),
            updateTime: DateTime.now(),
          )
        ];

        final projectApiResponse = ApiResponse<List<ProjectModel>>(
          success: true,
          message: '成功',
          data: projects,
        );

        final todos = [
          TodoModel(
            id: 1,
            projectId: 1,
            title: '任务1',
            description: '任务1描述',
            status: TodoStatus.todo,
            priority: Priority.high,
            todoType: TodoType.develop,
            reporterId: 1,
            createTime: DateTime.now(),
            updateTime: DateTime.now(),
          )
        ];

        final todoApiResponse = ApiResponse<List<TodoModel>>(
          success: true,
          message: '成功',
          data: todos,
        );

        final notes = [
          NoteModel(
            id: 1,
            title: '笔记1',
            content: '笔记1内容',
            noteType: NoteType.general,
            tags: ['测试'],
            authorId: 1,
            isPublic: true,
            createTime: DateTime.now(),
            updateTime: DateTime.now(),
          )
        ];

        final noteApiResponse = ApiResponse<List<NoteModel>>(
          success: true,
          message: '成功',
          data: notes,
        );

        // 设置Mock行为
        when(mockAuthApiService.getCurrentUser()).thenAnswer((_) async => userApiResponse);
        when(mockProjectApiService.getMyProjects()).thenAnswer((_) async => projectApiResponse);
        when(mockTodoApiService.getTodos()).thenAnswer((_) async => todoApiResponse);
        when(mockNoteApiService.getNotes()).thenAnswer((_) async => noteApiResponse);
        when(mockOfflineSyncService.hasPendingOperations()).thenAnswer((_) async => false);
        when(mockDatabase.insertUser(any)).thenAnswer((_) async => 1);
        when(mockDatabase.insertProject(any)).thenAnswer((_) async => 1);
        when(mockDatabase.insertTodo(any)).thenAnswer((_) async => 1);
        when(mockDatabase.insertNote(any)).thenAnswer((_) async => 1);

        // 监听同步状态变化
        final statusList = <SyncStatus>[];
        dataSyncService.syncStatus.listen((status) {
          statusList.add(status);
        });

        // 监听同步进度变化
        final progressList = <double>[];
        dataSyncService.syncProgress.listen((progress) {
          progressList.add(progress);
        });

        // 执行同步
        await dataSyncService.syncAllData();

        // 验证状态变化
        expect(statusList, contains(SyncStatus.syncing));
        expect(statusList, contains(SyncStatus.completed));
        
        // 验证进度变化
        expect(progressList, isNotEmpty);
        expect(progressList.last, 1.0);

        // 验证方法调用
        verify(mockAuthApiService.getCurrentUser()).called(1);
        verify(mockProjectApiService.getMyProjects()).called(1);
        verify(mockTodoApiService.getTodos()).called(1);
        verify(mockNoteApiService.getNotes()).called(1);
        verify(mockOfflineSyncService.hasPendingOperations()).called(1);
      });

      test('同步失败时更新状态为失败', () async {
        // 设置Mock行为，模拟API调用失败
        when(mockAuthApiService.getCurrentUser()).thenThrow(Exception('网络错误'));

        // 监听同步状态变化
        final statusList = <SyncStatus>[];
        dataSyncService.syncStatus.listen((status) {
          statusList.add(status);
        });

        // 执行同步
        await dataSyncService.syncAllData();

        // 验证状态变化
        expect(statusList, contains(SyncStatus.syncing));
        expect(statusList, contains(SyncStatus.failed));
      });
    });

    group('同步用户数据', () {
      test('成功同步用户数据', () async {
        // 准备测试数据
        final userInfo = UserInfo(
          id: 1,
          username: 'testuser',
          email: 'test@example.com',
          role: 'DEVELOPER',
        );

        final apiResponse = ApiResponse<UserInfo>(
          success: true,
          message: '成功',
          data: userInfo,
        );

        // 设置Mock行为
        when(mockAuthApiService.getCurrentUser()).thenAnswer((_) async => apiResponse);
        when(mockDatabase.insertUser(any)).thenAnswer((_) async => 1);

        // 执行同步（通过反射访问私有方法）
        // 注意：在实际测试中，我们可能需要使用测试友好的设计模式

        // 验证方法调用
        verify(mockAuthApiService.getCurrentUser()).called(1);
      });
    });

    group('同步项目数据', () {
      test('成功同步项目数据', () async {
        // 准备测试数据
        final projects = [
          ProjectModel(
            id: 1,
            projectName: '项目1',
            description: '项目1描述',
            status: ProjectStatus.inProgress,
            priority: Priority.high,
            creatorId: 1,
            createTime: DateTime.now(),
            updateTime: DateTime.now(),
          )
        ];

        final apiResponse = ApiResponse<List<ProjectModel>>(
          success: true,
          message: '成功',
          data: projects,
        );

        // 设置Mock行为
        when(mockProjectApiService.getMyProjects()).thenAnswer((_) async => apiResponse);
        when(mockDatabase.insertProject(any)).thenAnswer((_) async => 1);

        // 验证方法调用
        verify(mockProjectApiService.getMyProjects()).called(1);
      });
    });

    group('同步待办数据', () {
      test('成功同步待办数据', () async {
        // 准备测试数据
        final todos = [
          TodoModel(
            id: 1,
            projectId: 1,
            title: '任务1',
            description: '任务1描述',
            status: TodoStatus.todo,
            priority: Priority.high,
            todoType: TodoType.develop,
            reporterId: 1,
            createTime: DateTime.now(),
            updateTime: DateTime.now(),
          )
        ];

        final apiResponse = ApiResponse<List<TodoModel>>(
          success: true,
          message: '成功',
          data: todos,
        );

        // 设置Mock行为
        when(mockTodoApiService.getTodos()).thenAnswer((_) async => apiResponse);
        when(mockDatabase.insertTodo(any)).thenAnswer((_) async => 1);

        // 验证方法调用
        verify(mockTodoApiService.getTodos()).called(1);
      });
    });

    group('同步笔记数据', () {
      test('成功同步笔记数据', () async {
        // 准备测试数据
        final notes = [
          NoteModel(
            id: 1,
            title: '笔记1',
            content: '笔记1内容',
            noteType: NoteType.general,
            tags: ['测试'],
            authorId: 1,
            isPublic: true,
            createTime: DateTime.now(),
            updateTime: DateTime.now(),
          )
        ];

        final apiResponse = ApiResponse<List<NoteModel>>(
          success: true,
          message: '成功',
          data: notes,
        );

        // 设置Mock行为
        when(mockNoteApiService.getNotes()).thenAnswer((_) async => apiResponse);
        when(mockDatabase.insertNote(any)).thenAnswer((_) async => 1);

        // 验证方法调用
        verify(mockNoteApiService.getNotes()).called(1);
      });
    });

    group('网络状态变化处理', () {
      test('网络连接恢复时触发数据同步', () async {
        // 监听同步状态变化
        final statusList = <SyncStatus>[];
        dataSyncService.syncStatus.listen((status) {
          statusList.add(status);
        });

        // 模拟网络连接恢复
        // 注意：在实际测试中，我们需要更好的方式来触发这个回调

        // 验证同步被触发
        // 这个测试需要更复杂的设置来验证网络状态变化的处理
      });
    });
  });
}